package com.grupoconstruobras.sigo.general.reporte;

import com.grupoconstruobras.sigo.general.ApplicationBean;
import com.grupoconstruobras.sigo.general.util.ManagedBeanUtils;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRPdfExporterParameter;

@Named(value = "reporteManager")
@SessionScoped
public class ReportesManager implements Serializable {

	private static final long serialVersionUID = -7097687614769591227L;
	private List<String> bienesSeleccionados = new ArrayList<String>();

	private Map<String, Object> parametros = new HashMap<String, Object>();


	private Connection connection;

	@Inject
	private HttpServletRequest request;

	@Inject
	@Named("applicationBean")
	private ApplicationBean applicationBean;

	public String cancelar() {
		this.clearData();
		return null;
	}

	private Connection getConnection() throws ClassNotFoundException,
			SQLException, NamingException {
		if (connection == null || connection.isClosed()) {
			Context initContext = new InitialContext();
			DataSource ds = (DataSource) initContext
					.lookup("java:/sijypDatasource");
			connection = ds.getConnection();
		}
		return connection;
	}

	private String getReportJRXMLPath(ServletContext context, String name) {
		String path = "/resources/reportes/";
		String filepath = path + name + ".jrxml";
		String realPath = context.getRealPath(filepath);
		return realPath;
	}

	public String getRealPathToReport(String name) {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		ExternalContext externalContext = facesContext.getExternalContext();
		ServletContext context = (ServletContext) externalContext.getContext();
		String realPath = getReportJRXMLPath(context, name);
		return realPath;
	}

	public JasperReportGenerator getGenerator(String name)
			throws ClassNotFoundException, SQLException, NamingException {
		JasperReportGenerator generator = JasperReportGenerator
				.getInstance(name);
		Connection connection = getConnection();
		generator.setConnection(connection);
		String path = getRealPathToReport(name);
		generator.setFilepath(path);
		return generator;
	}

	public HttpServletResponse getResponse() {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		ExternalContext externalContext = facesContext.getExternalContext();
		return (HttpServletResponse) externalContext.getResponse();
	}

	private void mostrarError(String error, Severity severity) {
		ResourceBundle bundle = ManagedBeanUtils.getMessagesBundle();
		String text = bundle.getString(error);
		FacesMessage message = new FacesMessage(severity, text, null);
		FacesContext facesContext = FacesContext.getCurrentInstance();
		facesContext.addMessage(null, message);
	}

	private void mostrarError(String error) {
		mostrarError(error, FacesMessage.SEVERITY_WARN);
	}

	public HttpServletResponse getHttpServletResponse(String name) {
		HttpServletResponse response = getResponse();
		response.setHeader("Content-Type", "application/pdf");
		response.setHeader("Content-Disposition", "attachment;filename=" + name
				+ ".pdf");
		return response;
	}

	public void prepararReporte(String name) throws JRException,
			ClassNotFoundException, SQLException, NamingException, IOException {
		JasperReportGenerator generator = getGenerator(name);
		generator.addOptions(bienesSeleccionados);
		generator.addParameters(parametros);
		generator.setIdUser(request.getUserPrincipal().getName());
		hacerReporte(generator);
		this.clearData();
	}

	public void prepararReporte(String name, String option) throws JRException,
			ClassNotFoundException, SQLException, NamingException, IOException {
		JasperReportGenerator generator = getGenerator(name);
		generator.addOption(option);
		generator.setIdUser(request.getUserPrincipal().getName());
		generator.addParameter("id_bien", Integer.valueOf(option));
		hacerReporteSinResultset(generator);
		this.clearData();
	}

	public String crearReporte(String name, String option) {
		try {
			prepararReporte(name, option);
		} catch (ClassNotFoundException e) {
			mostrarError("general.error.base.datos");
			e.printStackTrace();
//			throw new AssertionError(e);
		} catch (JRException e) {
			mostrarError("general.error.base.datos");
			e.printStackTrace();
//			throw new AssertionError(e);
		} catch (NamingException e) {
			mostrarError("general.error.base.datos");
			e.printStackTrace();
//			throw new AssertionError(e);
		} catch (SQLException e) {
			mostrarError("general.error.base.datos");
			e.printStackTrace();
		} catch (IOException e) {
			mostrarError("general.error.io");
			e.printStackTrace();
		} finally {
			try {
				connection.close();
			} catch (SQLException e) {
				mostrarError("general.error.base.datos");
				e.printStackTrace();
			}
		}
		return "";
	}

	public String crearReporte(String name) {
		try {
			prepararReporte(name);
		} catch (ClassNotFoundException e) {
			mostrarError("general.error.base.datos");
			e.printStackTrace();
//			throw new AssertionError(e);
		} catch (JRException e) {
			mostrarError("general.error.base.datos");
			e.printStackTrace();
//			throw new AssertionError(e);
		} catch (SQLException e) {
			mostrarError("general.error.base.datos");
			e.printStackTrace();
		} catch (NamingException e) {
			mostrarError("general.error.base.datos");
			e.printStackTrace();
		} catch (IOException e) {
			mostrarError("general.error.base.datos");
			e.printStackTrace();
		} finally {
			try {
				connection.close();
			} catch (SQLException e) {
				mostrarError("general.error.base.datos");
				e.printStackTrace();
			}
		}
		return "";
	}

	public List<String> getBienesSeleccionados() {
		return bienesSeleccionados;
	}

	public void setBienesSeleccionados(List<String> bienesSeleccionados) {
		this.bienesSeleccionados = bienesSeleccionados;
	}

	private void hacerReporte(JasperReportGenerator generator)
			throws JRException, SQLException, IOException,
			ClassNotFoundException, NamingException {

		generator.generarReporte();
		generator.generarResultSet();
		if (generator.estaElResultSetVacio()) {
			mostrarError("reportes.resultset.vacio");
			return;
		}

		JasperPrint print;
		if (generator.getName().equals("reporte_general_bien")) {
			print = generator.obtenerPrint(getConnection());
		} else {
			print = generator.obtenerPrint();
		}

		JRPdfExporter exporter = new JRPdfExporter();
		exporter.setParameter(JRPdfExporterParameter.JASPER_PRINT, print);
		HttpServletResponse response = getResponse();
		OutputStream output = response.getOutputStream();
		exporter.setParameter(JRPdfExporterParameter.OUTPUT_STREAM, output);
		exporter.setParameter(JRPdfExporterParameter.OUTPUT_STREAM, output);
		response.setHeader("Content-Type", "application/pdf");
		response.setHeader("Content-Disposition", "attachment;filename="
				+ generator.getName() + ".pdf");
		exporter.exportReport();
		FacesContext facesContext = FacesContext.getCurrentInstance();
		facesContext.responseComplete();
		output.close();
	}

	private void hacerReporteSinResultset(JasperReportGenerator generator)
			throws JRException, SQLException, IOException,
			ClassNotFoundException, NamingException {

		generator.generarReporte();
		JasperPrint print = generator.obtenerPrint(getConnection());

		JRPdfExporter exporter = new JRPdfExporter();
		exporter.setParameter(JRPdfExporterParameter.JASPER_PRINT, print);
		HttpServletResponse response = getResponse();
		OutputStream output = response.getOutputStream();
		exporter.setParameter(JRPdfExporterParameter.OUTPUT_STREAM, output);
		exporter.setParameter(JRPdfExporterParameter.OUTPUT_STREAM, output);
		response.setHeader("Content-Type", "application/pdf");
		response.setHeader("Content-Disposition", "attachment;filename="
				+ generator.getName() + ".pdf");
		exporter.exportReport();
		FacesContext facesContext = FacesContext.getCurrentInstance();
		facesContext.responseComplete();
		output.close();
	}

	public void clearData() {
		this.bienesSeleccionados = new ArrayList<String>();
		this.parametros = new HashMap<String, Object>();
	}

	public String getPais() {
		return (String) parametros.get("idPais");
	}

	public void setPais(String idPais) {
		parametros.put("idPais", idPais);
		if (idPais != null && !idPais.isEmpty()) {
			String nombre = applicationBean.getNombrePais(Integer
					.parseInt(idPais));
			parametros.put("pais", nombre);
		}
	}

	public String getDepartamento() {
		return (String) parametros.get("idDepartamento");
	}

	public void setDepartamento(String idDepartamento) {
		parametros.put("idDepartamento", idDepartamento);
		if (idDepartamento != null && !idDepartamento.isEmpty()) {
			String nombre = applicationBean.getNombreDepartamento(Integer
					.parseInt(idDepartamento));
			parametros.put("departamento", nombre);
		}
	}

	public String getMunicipio() {
		return (String) parametros.get("idMunicipio");
	}

	public void setMunicipio(String idMunicipio) {
		parametros.put("idMunicipio", idMunicipio);
		if (idMunicipio != null && !idMunicipio.isEmpty()) {
			String nombre = applicationBean.getNombreMunicipio(Integer
					.parseInt(idMunicipio));
			parametros.put("municipio", nombre);
		}
	}

}
